package top.cardone.security.impl;

import com.google.common.base.Charsets;
import com.google.common.collect.Maps;
import lombok.Setter;
import org.apache.commons.codec.binary.Base64;
import top.cardone.core.CodeException;
import top.cardone.security.Descipher;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.util.Map;

/**
 * Created by yht on 16-2-2.
 */
public class DescipherImpl implements Descipher {
    @Setter
    private String keyAlgorithm = "AES";

    @Setter
    private String CipherAlgorithm = "AES";

    @Setter
    private String key = "cardone.";

    private Map<String, Cipher> cipherMap = Maps.newConcurrentMap();

    private Cipher getCipher(String salt, int mode) throws Exception {
        String key = this.key + salt + "." + mode;

        Cipher cipher = cipherMap.get(key);

        if (cipher == null) {
            SecretKeySpec keyspec = new SecretKeySpec(org.apache.commons.codec.digest.DigestUtils.md5(key + salt), keyAlgorithm);

            cipher = Cipher.getInstance(CipherAlgorithm);

            cipher.init(mode, keyspec);

            cipherMap.put(key, cipher);
        }

        return cipher;
    }

    @Override
    public String encrypt(String salt, String text) {
        try {
            Cipher cipher = this.getCipher(salt, Cipher.ENCRYPT_MODE);

            byte[] encrypted = cipher.doFinal(text.getBytes(Charsets.UTF_8));

            return Base64.encodeBase64String(encrypted);
        } catch (Exception e) {
            throw new CodeException("000000", e);
        }
    }

    @Override
    public String decrypt(String salt, String text) {
        try {
            Cipher cipher = this.getCipher(salt, Cipher.DECRYPT_MODE);

            byte[] original = cipher.doFinal(Base64.decodeBase64(text));

            String originalString = new String(original, Charsets.UTF_8);

            return originalString;
        } catch (Exception e) {
            throw new CodeException("000000", e);
        }
    }
}

